Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
http2-wrapper
Advanced tools
The http2-wrapper npm package is a module that provides an easy-to-use wrapper around the native HTTP/2 client and server capabilities in Node.js. It simplifies the process of making HTTP/2 requests and handling responses, as well as creating HTTP/2 servers.
Making HTTP/2 requests
This feature allows you to make HTTP/2 requests to a server. The code sample demonstrates how to perform a simple GET request using the http2-wrapper.
const http2wrapper = require('http2-wrapper');
const options = {
hostname: 'example.com',
protocol: 'https:',
path: '/',
method: 'GET'
};
http2wrapper.request(options, (res) => {
console.log(`Status Code: ${res.statusCode}`);
res.on('data', (chunk) => {
console.log(chunk);
});
}).end();
Creating HTTP/2 servers
This feature allows you to create an HTTP/2 server. The code sample shows how to set up a simple HTTP/2 server that responds with 'Hello World' to all requests.
const http2wrapper = require('http2-wrapper');
const http2 = require('http2');
const server = http2.createSecureServer({
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem')
});
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html',
':status': 200
});
stream.end('<h1>Hello World</h1>');
});
http2wrapper.createServer(server).listen(8443);
The 'spdy' package is an HTTP/2 and SPDY protocol client and server implementation for Node.js. It provides similar functionalities to http2-wrapper but also includes support for SPDY, which is a now-deprecated protocol that was a precursor to HTTP/2.
While 'node-fetch' is primarily a light-weight module that brings window.fetch to Node.js, it can be used to make HTTP/2 requests when combined with the built-in http2 module in Node.js. It does not provide server capabilities like http2-wrapper.
HTTP/2 client, just with the familiar
https
API
This package was created to support HTTP/2 without the need to rewrite your code.
I recommend adapting to the http2
module if possible - it's much simpler to use and has many cool features!
Tip: http2-wrapper
is very useful when you rely on other modules that use the HTTP/1 API and you want to support HTTP/2.
Pro Tip: While the native http2
doesn't have agents yet, you can use http2-wrapper
Agents and still operate on the native HTTP/2 streams.
$ npm install http2-wrapper
$ yarn add http2-wrapper
const http2 = require('http2-wrapper');
const options = {
hostname: 'nghttp2.org',
protocol: 'https:',
path: '/httpbin/post',
method: 'POST',
headers: {
'content-length': 6
}
};
const request = http2.request(options, response => {
console.log('statusCode:', response.statusCode);
console.log('headers:', response.headers);
const body = [];
response.on('data', chunk => {
body.push(chunk);
});
response.on('end', () => {
console.log('body:', Buffer.concat(body).toString());
});
});
request.on('error', console.error);
request.write('123');
request.end('456');
// statusCode: 200
// headers: [Object: null prototype] {
// ':status': 200,
// date: 'Fri, 27 Sep 2019 19:45:46 GMT',
// 'content-type': 'application/json',
// 'access-control-allow-origin': '*',
// 'access-control-allow-credentials': 'true',
// 'content-length': '239',
// 'x-backend-header-rtt': '0.002516',
// 'strict-transport-security': 'max-age=31536000',
// server: 'nghttpx',
// via: '1.1 nghttpx',
// 'alt-svc': 'h3-23=":4433"; ma=3600',
// 'x-frame-options': 'SAMEORIGIN',
// 'x-xss-protection': '1; mode=block',
// 'x-content-type-options': 'nosniff'
// }
// body: {
// "args": {},
// "data": "123456",
// "files": {},
// "form": {},
// "headers": {
// "Content-Length": "6",
// "Host": "nghttp2.org"
// },
// "json": 123456,
// "origin": "xxx.xxx.xxx.xxx",
// "url": "https://nghttp2.org/httpbin/post"
// }
Note: The session
option was renamed to tlsSession
for better readability.
Note: The timeout
option applies to HTTP/2 streams only. In order to set session timeout, pass an Agent with custom timeout
option set.
Performs ALPN negotiation.
Returns a Promise giving proper ClientRequest
instance (depending on the ALPN).
Note: The agent
option represents an object with http
, https
and http2
properties.
const http2 = require('http2-wrapper');
const options = {
hostname: 'httpbin.org',
protocol: 'http:', // Try changing this to https:
path: '/post',
method: 'POST',
headers: {
'content-length': 6
}
};
(async () => {
try {
const request = await http2.auto(options, response => {
console.log('statusCode:', response.statusCode);
console.log('headers:', response.headers);
const body = [];
response.on('data', chunk => body.push(chunk));
response.on('end', () => {
console.log('body:', Buffer.concat(body).toString());
});
});
request.on('error', console.error);
request.write('123');
request.end('456');
} catch (error) {
console.error(error);
}
})();
// statusCode: 200
// headers: { connection: 'close',
// server: 'gunicorn/19.9.0',
// date: 'Sat, 15 Dec 2018 18:19:32 GMT',
// 'content-type': 'application/json',
// 'content-length': '259',
// 'access-control-allow-origin': '*',
// 'access-control-allow-credentials': 'true',
// via: '1.1 vegur' }
// body: {
// "args": {},
// "data": "123456",
// "files": {},
// "form": {},
// "headers": {
// "Connection": "close",
// "Content-Length": "6",
// "Host": "httpbin.org"
// },
// "json": 123456,
// "origin": "xxx.xxx.xxx.xxx",
// "url": "http://httpbin.org/post"
// }
An instance of quick-lru
used for ALPN cache.
There is a maximum of 100 entries. You can modify the limit through protocolCache.maxSize
- note that the change will be visible globally.
Type: Map<string, string>
This is the store where cached ALPN protocols are put into.
Type: Map<string, Promise>
This is the store that contains pending ALPN negotiation promises.
Type: (options, callback) => TLSSocket | Promise<TLSSocket>
See https://github.com/szmarczak/resolve-alpn#connect
Returns a Promise<{alpnProtocol: string}>
.
Same as https.request
.
Type: Http2Session
The session used to make the actual request. If none provided, it will use options.agent
to get one.
Same as https.get
.
Same as https.ClientRequest
.
Same as https.IncomingMessage
.
Note: this is not compatible with the classic http.Agent
.
Usage example:
const http2 = require('http2-wrapper');
class MyAgent extends http2.Agent {
createConnection(origin, options) {
console.log(`Connecting to ${http2.Agent.normalizeOrigin(origin)}`);
return http2.Agent.connect(origin, options);
}
}
http2.get({
hostname: 'google.com',
agent: new MyAgent()
}, response => {
response.on('data', chunk => console.log(`Received chunk of ${chunk.length} bytes`));
});
Each option is an Agent
property and can be changed later.
Type: number
Default: 0
If there's no activity after timeout
milliseconds, the session will be closed. If 0
, no timeout is applied.
Type: number
Default: Infinity
The maximum amount of sessions in total.
Type: number
Default: 10
The maximum amount of empty sessions in total. An empty session is a session with no pending requests.
Type: number
Default: 100
The maximum amount of cached TLS sessions.
Type: string
Default: https:
Type: object
Default: {enablePush: false}
Settings used by the current agent instance.
Returns a string representing normalized options.
Agent.normalizeOptions({servername: 'example.com'});
// => ':::::::::::::::::::::::::::::::::::::'
Type: string
URL
object
Origin used to create new session.
Type: object
Options used to create new session.
Returns a Promise giving free Http2Session
. If no free sessions are found, a new one is created.
A session is considered free when pending streams count is less than max concurrent streams settings.
Type: object
{
reject: error => void,
resolve: session => void
}
If the listener
argument is present, the Promise will resolve immediately. It will use the resolve
function to pass the session.
Returns a Promise giving Http2Stream
.
Returns a new TLSSocket
. It defaults to Agent.connect(origin, options)
.
Type: number
Default: Number.POSITIVE_INFINITY
Makes an attempt to close empty sessions. Only sessions with 0 concurrent streams will be closed.
Destroys all sessions.
Type: number
A number of empty sessions.
Type: number
A number of pending sessions.
Type: number
A number of all sessions held by the Agent.
agent.on('session', session => {
// A new session has been created by the Agent.
});
Currently http2-wrapper
provides support for these proxies:
HttpOverHttp2
HttpsOverHttp2
Http2OverHttp2
Http2OverHttp
Http2OverHttps
Any of the above can be accessed via http2wrapper.proxies
. Check out the examples/proxies
directory to learn more.
Note: If you use the http2.auto
function, the real IP address will leak. http2wrapper
is not aware of the context. It will create a connection to the end server using your real IP address to get the ALPN protocol. Then it will create another connection using proxy. To migitate this, you need to pass a custom resolveProtocol
function as an option:
const resolveAlpnProxy = new URL('https://username:password@localhost:8000');
const connect = async (options, callback) => new Promise((resolve, reject) => {
const host = `${options.host}:${options.port}`;
(async () => {
try {
const request = await http2.auto(resolveAlpnProxy, {
method: 'CONNECT',
headers: {
host
},
path: host,
// For demo purposes only!
rejectUnauthorized: false,
});
request.end();
request.once('error', reject);
request.once('connect', (response, socket, head) => {
if (head.length > 0) {
reject(new Error(`Unexpected data before CONNECT tunnel: ${head.length} bytes`));
socket.destroy();
return;
}
const tlsSocket = tls.connect({
...options,
socket
}, callback);
resolve(tlsSocket);
});
} catch (error) {
reject(error);
}
})();
});
// This is required to prevent leaking real IP address on ALPN negotiation
const resolveProtocol = http2.auto.createResolveProtocol(new Map(), new Map(), connect);
const request = await http2.auto('https://httpbin.org/anything', {
agent: {…},
resolveProtocol
}, response => {
// Read the response here
});
request.end();
See unknown-over-unknown.js
to learn more.
See examples/proxies/mirror.js
for an example.
See examples/ws
for an example.
See examples/push-stream
for an example.
got
- Simplified HTTP requestshttp2-proxy
- A simple http/2 & http/1.1 spec compliant proxy helper for Node.MIT
FAQs
HTTP2 client, just with the familiar `https` API
The npm package http2-wrapper receives a total of 7,559,421 weekly downloads. As such, http2-wrapper popularity was classified as popular.
We found that http2-wrapper demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.